package org.hzz.promotions.domain.service.impl;

import io.gitee.pkmer.common.collection.CollUtil;
import io.gitee.pkmer.convention.exception.request.BadRequestException;
import io.gitee.pkmer.convention.page.PageResponse;
import io.gitee.pkmer.convention.page.query.PageQuery;
import io.gitee.pkmer.convention.service.BaseDomainService;
import lombok.Setter;
import org.hzz.promotions.domain.entity.CouponEntity;
import org.hzz.promotions.domain.repository.CouponRepository;
import org.hzz.promotions.domain.service.CouponDomainService;
import org.hzz.promotions.domain.service.CouponScopeDomainService;
import org.hzz.promotions.domain.service.ExchangeCodeDomainService;
import org.hzz.promotions.types.enums.coupon.CouponStatus;
import org.hzz.promotions.types.enums.coupon.ObtainWay;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author <a href="mailto:1193094618@qq.com">pkmer</a>
 * <br>
 * <a href = "https://gitee.com/pkmer/sonatype-central-publisher">Code Repository</a>
 * At 2024/8/29
 */
@Service
public class CouponDomainServiceImpl
        extends BaseDomainService<CouponRepository>
        implements CouponDomainService {

    @Setter(onMethod_ = @Autowired)
    private ExchangeCodeDomainService codeDomainService;

    @Setter(onMethod_ = @Autowired)
    private CouponScopeDomainService scopeDomainService;

    /**
     * {@inheritDoc}
     * @param coupon 优惠券实体
     */
    @Override
    public void insertCoupon(CouponEntity coupon) {
        repository.insertCoupon(coupon);
    }

    /**
     * {@inheritDoc}
     * @param entity 优惠券实体
     */
    @Override
    public void updateCouponEntity(CouponEntity entity) {
        CouponEntity coupon = getCouponEntityById(entity.getId());
        if(coupon.getStatus() != CouponStatus.DRAFT){
            throw new BadRequestException("该优惠不允许修改,此时状态为："+coupon.getStatus().getDesc());
        }

        repository.updateCoupon(entity);
    }

    @Override
    public void batchUpdateCouponEntity(List<CouponEntity> entities) {
        repository.batchUpdateCouponEntity(entities);
    }

    @Override
    public CouponEntity getCouponEntity(Long id) {
        return getCouponEntityById(id);
    }

    /**
     * {@inheritDoc}
     * @param pageQuery 分页查询
     * @return  分页结果
     */
    @Override
    public PageResponse<CouponEntity> pageQueryCoupon(PageQuery pageQuery) {
        return repository.pageQueryCoupon(pageQuery);
    }

    @Override
    public void beginIssue(CouponEntity couponEntity) {
        CouponEntity coupon = getCouponEntityById(couponEntity.getId());
        // 优惠券当前状态必须是暂停或草稿
        if(coupon.getStatus() != CouponStatus.PAUSE && coupon.getStatus() != CouponStatus.DRAFT){
            throw new BadRequestException("优惠券修改发布错误");
        }

        LocalDateTime now = LocalDateTime.now();
        LocalDateTime issueBeginTime = couponEntity.getIssueBeginTime();
        // 立即方法没有开始放发时间,就在此时此刻开始，可以领取优惠券
        boolean isBegin = issueBeginTime == null || issueBeginTime.isBefore(now);

        if(isBegin){
            couponEntity.setIssueBeginTime(now);
            // 优惠券处于放发状态
            couponEntity.setStatus(CouponStatus.ISSUING);
        }else{
            couponEntity.setStatus(CouponStatus.UN_ISSUE);
        }
        repository.updateCoupon(couponEntity);

        // 优惠券处于未发布状态并且是兑换码方式，则异步生成兑换码
        if(coupon.getStatus() == CouponStatus.DRAFT
                && coupon.getObtainWay() == ObtainWay.CODE){
            codeDomainService.asyncGenerateCode(
                    coupon.getId(),
                    coupon.getTotalNum(),
                    couponEntity.getIssueEndTime());
        }
    }

    /**
     * {@inheritDoc}
     * @param id 优惠券id
     */
    @Override
    public void pauseCoupon(Long id) {
        CouponEntity entity = new CouponEntity();
        CouponEntity coupon = getCouponEntityById(id);

        if(CouponStatus.ISSUING != coupon.getStatus()){
            throw new BadRequestException("优惠券不在发放中，不能暂停");
        }
        entity.setId(id).setStatus(CouponStatus.PAUSE);

        repository.updateCoupon(entity);
    }



    @Override
    public void deleteCoupon(Long id) {
        CouponEntity coupon = getCouponEntityById(id);
        if(coupon.getStatus() != CouponStatus.DRAFT){
            throw new BadRequestException(String.format("优惠券状态不是处于%s不能删除",CouponStatus.DRAFT.getDesc()));
        }
        // 删除数据库的优惠券
        repository.deleteCoupon(id);
        // 删除范围
        if(coupon.getSpecific()){
            scopeDomainService.deleteCouponScope(coupon.getId());
        }
        // 删除兑换码
        if(coupon.getObtainWay() == ObtainWay.CODE){
            codeDomainService.deleteCouponCodeByTargetId(coupon.getId());
        }

    }

    @Override
    public void incrementIssueNum(long id) {
        final int num = 1;
        int row = repository.incrementIssueNum(id,num);
        if(row == 0){
            throw new BadRequestException("领取优惠券失败 id = "+id);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<CouponEntity> getCouponEntityByIds(List<Long> ids) {
        return repository.getCouponByIds(ids);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<Long, CouponEntity> getCouponEntityMapById(List<Long> ids) {

        if(CollUtil.isEmpty(ids)) return Collections.emptyMap();
        List<CouponEntity> coupons = getCouponEntityByIds(ids);

        return coupons.stream().collect(Collectors.toMap(
                CouponEntity::getId,
                c -> c
        ));
    }


    /**
     * 根据id获取优惠券实体
     * @param id 优惠券id
     */
    private CouponEntity getCouponEntityById(Long id){
        Optional<CouponEntity> couponOptional = repository.getCouponById(id);
        return couponOptional.orElseThrow(() -> new BadRequestException("优惠券不存在"));
    }
}
